package com.decent.manager.system.auth.jwt;

import cn.hutool.json.JSONUtil;
import cn.hutool.jwt.JWT;
import cn.hutool.jwt.JWTUtil;
import cn.hutool.jwt.signers.JWTSigner;
import cn.hutool.jwt.signers.JWTSignerUtil;
import lombok.extern.slf4j.Slf4j;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.Optional;

/**
 * @author 张子旭
 * @date 2022/1/20
 */
@Slf4j
public class JwtTokenUtil {
    /**
     * 过期时间
     */
    private static final long EXPIRE_TIME = 24 * 60 * 60 * 1000;
    /**
     * 密钥盐
     */
    private static final String TOKEN_SECRET = "2A33103E269D4847A427388D65054D27";

    private static final String ISSUE = "user";

    /**
     * 生成token
     */
    public static String sign(JwtPayLoad jwtPayLoad) {
        Date expiresAt = new Date(System.currentTimeMillis() + EXPIRE_TIME);
        JWTSigner signer = JWTSignerUtil.hs384(TOKEN_SECRET.getBytes());
        JWT jwt = JWT.create().setPayload("data", JSONUtil.toJsonStr(jwtPayLoad))
                .setIssuer(ISSUE)
                .setExpiresAt(expiresAt)
                .setSigner(signer);
        return jwt.sign();
    }

    /**
     * 获取JwtPayLoad部分
     */
    public static JwtPayLoad getJwtPayLoad(String token) {
        JWT jwt = JWTUtil.parseToken(token);
        return JSONUtil.toBean(jwt.getPayload("data").toString(), JwtPayLoad.class);
    }

    /**
     * 校验token是否正确
     */
    public static Boolean checkToken(String token) {
        try {
            JWTSigner signer = JWTSignerUtil.hs384(TOKEN_SECRET.getBytes());
            return JWTUtil.verify(token, signer);
        } catch (Exception jwtException) {
            return false;
        }
    }

    /**
     * 校验token是否失效
     */
    public static Boolean isTokenExpired(String token) {
        try {
            JWT parseToken = JWTUtil.parseToken(token);
            Object exp = Optional.ofNullable(parseToken.getPayload("exp")).orElse(0);
            return LocalDateTime.now().isAfter(new Date(Long.parseLong(exp.toString()) * 1000).toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime());
        } catch (Exception expiredJwtException) {
            return true;
        }
    }
}
